package com.wyg.blog.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wyg.blog.config.RsaKeyProperties;
import com.wyg.blog.service.serviceimpl.MyUserDetailsServiceImpl;
import com.wyg.blog.utils.JwtTokenUtil;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;

/**
 * @description:
 * @author: WYG
 * @time: 2020/6/22 20:31
 */

public class MyOncePerRequestFilter extends OncePerRequestFilter {

    private MyUserDetailsServiceImpl myUserDetailsService;


    private RsaKeyProperties rsaKeyProperties;

    public MyOncePerRequestFilter(RsaKeyProperties rsaKeyProperties, MyUserDetailsServiceImpl myUserDetailsService){
        this.rsaKeyProperties = rsaKeyProperties;
        this.myUserDetailsService = myUserDetailsService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        String header = httpServletRequest.getHeader("Authorization");
        httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
        httpServletResponse.setHeader("Access-Control-Allow-Method", "POST,GET");
        if(!StringUtils.isEmpty(header)){
            String token = header.replace("Bearer","").trim();
            PublicKey publicKey = rsaKeyProperties.getPublicKey();
            System.out.println("token:"+token);
            boolean check = JwtTokenUtil.isTokenExpired(token,publicKey);
            System.out.println(check);
            if(!check){
                String username = JwtTokenUtil.getUsernameFromToken(token, rsaKeyProperties.getPublicKey());
                UserDetails userDetails = myUserDetailsService.loadUserByUsername(username);
                if(username != null && SecurityContextHolder.getContext().getAuthentication() == null){
                    boolean validate = JwtTokenUtil.validate(token,username,rsaKeyProperties.getPublicKey());
                    if(validate){
                        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails,
                                null,userDetails.getAuthorities());
                        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                        filterChain.doFilter(httpServletRequest,httpServletResponse);
                    }
                }
            } else {
                filterChain.doFilter(httpServletRequest,httpServletResponse);
                httpServletResponse.setContentType("application/json;charset=utf-8");
                httpServletResponse.setStatus(601);
                PrintWriter out = httpServletResponse.getWriter();
                Map resultMap = new HashMap();
                resultMap.put("code", 601);
                resultMap.put("msg", "token已过期,请重新登录!");
                out.write(new ObjectMapper().writeValueAsString(resultMap));
                out.flush();
                out.close();
            }
        } else {
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            httpServletResponse.setContentType("application/json;charset=utf-8");
            httpServletResponse.setStatus(602);
            PrintWriter out = httpServletResponse.getWriter();
            Map resultMap = new HashMap();
            resultMap.put("code", 602);
            resultMap.put("msg", "用户未登录,请登录!");
            out.write(new ObjectMapper().writeValueAsString(resultMap));
            out.flush();
            out.close();
        }

    }
}
